/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "VssTool.h"
#include <string>
#include <cstring>
#include "log/Log.h"

namespace {
const std::string LOG_NAME = "vsstool.log";
const std::string LOG_PATH = R"(C:\\DataBackup\\ProtectClient\\ProtectClient-E\\log\\Plugins\\GeneralDBPlugin)";
const int LOG_LEVEL = 0;
const int LOG_COUNT = 100;
const int LOG_MAX_SIZE = 30;
}  // namespace

void PrintHelp()
{
    std::cout << "VSS Backup and Restore Command Instructions:" << std::endl;
    std::cout << "Enter \"VssBackup\" for Backup" << std::endl;
    std::cout << "Enter \"VssRestore\" for Restore" << std::endl;
}

void InitLog()
{
    Module::CLogger::GetInstance().Init(LOG_NAME.c_str(), LOG_PATH, LOG_LEVEL, LOG_COUNT, LOG_MAX_SIZE);
}

int main(int argc, char *argv[])
{
    InitLog();

    if (argc < LEAST_VSSTOOL_INPUT_COUNT) {
        HCP_Log(ERR, LOG_NAME) << "Not Enough Input!" << HCPENDLOG;
        return VSSTOOL_FAILED;
    }

    if (strcmp(argv[1], "Backup") == 0) {
        HCP_Log(INFO, LOG_NAME) << "Start Full Backup!" << HCPENDLOG;
        if (argc != BACKUP_INPUT_COUNT) {
            HCP_Log(ERR, LOG_NAME) << "Input Num Error!" << HCPENDLOG;
            return VSSTOOL_FAILED;
        }
        VssBackupWrapper backupInstance;
        const std::wstring sourcePath1 = backupInstance.Utf8ToUtf16(argv[2]) + L":\\";
        const std::wstring sourcePath2 = backupInstance.Utf8ToUtf16(argv[3]) + L":\\";
        const std::string targetWriterName = argv[4];
        const std::string guid = argv[5];
        const std::string targetBackupPath = argv[6];
        const std::string targetMetaPath = argv[7];

        std::vector<std::string> targetPath = {targetBackupPath, targetMetaPath};
        SnapshotSetResult result;
        std::vector<std::wstring> wVolumePathList = {sourcePath1};
        if (sourcePath1 != sourcePath2) {
            wVolumePathList.emplace_back(sourcePath2);
        }

        bool ret = backupInstance.ActualBackup(wVolumePathList, targetWriterName, guid, targetPath, result);
        std::string outputString = "";
        for (int i = 0; i < result.m_wSnapshotIDList.size(); i++) {
            std::string tempString = backupInstance.Utf16ToUtf8(result.m_wSnapshotIDList[i]);
            (i == 0) ? (outputString += tempString) : (outputString += "," + tempString);
        }
        // 无论成功失败，都需先向python输出快照id用于后置任务删除
        std::cout << outputString << std::endl;
        if (!ret) {
            HCP_Log(ERR, LOG_NAME) << "Backup Failed!" << HCPENDLOG;
            return VSSTOOL_FAILED;
        }
        return VSSTOOL_SUCCESS;
    } else if (strcmp(argv[1], "Restore") == 0) {
        HCP_Log(INFO, LOG_NAME) << "Start Restore!" << HCPENDLOG;
        // Usage: VssTool.exe
        // 1. Restore
        // 2. /path/to/backup/xml
        // 3. /path/to/writer/xml
        // 4. guid_of_database
        // 5. /path/to/data/repo
        // 5. /patn/to/restore

        std::string backupXmlPath = argv[2];
        std::string writerXmlPath = argv[3];
        std::string dataRepo = argv[4];
        std::string restorePath = argv[5];
        std::string guid = argv[6];

        dataRepo += "\\";
        restorePath += "\\";

        VssRestore restoreInstance;
        bool ret = restoreInstance.Restore(backupXmlPath, writerXmlPath, guid, dataRepo, restorePath);
        return VSSTOOL_SUCCESS;
    } else if (strcmp(argv[1], "Log") == 0) {
        HCP_Log(INFO, LOG_NAME) << "Start Log Backup!" << HCPENDLOG;
        if (argc != BACKUP_INPUT_COUNT) {
            HCP_Log(ERR, LOG_NAME) << "Input Num Error!" << HCPENDLOG;
            return VSSTOOL_FAILED;
        }
        VssLogWrapper logInstance;
        const std::wstring sourcePath1 = logInstance.Utf8ToUtf16(argv[2]) + L":\\";
        const std::wstring sourcePath2 = logInstance.Utf8ToUtf16(argv[3]) + L":\\";
        const std::string targetWriterName = argv[4];
        const std::string guid = argv[5];
        const std::string targetBackupPath = argv[6];
        const std::string targetMetaPath = argv[7];

        std::vector<std::string> targetPath = {targetBackupPath, targetMetaPath};
        SnapshotSetResult result;
        std::vector<std::wstring> wVolumePathList = {sourcePath1};
        if (sourcePath1 != sourcePath2) {
            wVolumePathList.emplace_back(sourcePath2);
        }
        bool ret = logInstance.ActualBackup(wVolumePathList, targetWriterName, guid, targetPath, result);
        std::string outputString = "";
        for (int i = 0; i < result.m_wSnapshotIDList.size(); i++) {
            std::string tempString = logInstance.Utf16ToUtf8(result.m_wSnapshotIDList[i]);
            (i == 0) ? (outputString += tempString) : (outputString += "," + tempString);
        }
        // 无论成功失败，都需先向python输出快照id用于后置任务删除
        std::cout << outputString << std::endl;
        if (!ret) {
            HCP_Log(ERR, LOG_NAME) << "Backup Failed!" << HCPENDLOG;
            return VSSTOOL_FAILED;
        }
        return VSSTOOL_SUCCESS;
    } else if (strcmp(argv[1], "Delete") == 0) {
        if (argc != DELETE_SNAPSHOT_INPUT_COUNT) {
            HCP_Log(ERR, LOG_NAME) << "Input Num Error!" << HCPENDLOG;
            return VSSTOOL_FAILED;
        }
        VssBackupWrapper backupInstance;
        std::string snapshotId = argv[2];
        std::wstring wSnapshotId = backupInstance.Utf8ToUtf16(snapshotId);
        VSS_ID vssSnapshotId = backupInstance.VssIDfromWStr(wSnapshotId);
        CHECK_BOOL_RETURN(backupInstance.DoDeleteSnapshot(vssSnapshotId), "DoDeleteSnapshot", VSSTOOL_FAILED);
        return VSSTOOL_SUCCESS;
    }

    return VSSTOOL_FAILED;
}